package com.soonzlab.englishlearning.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.dom4j.io.SAXReader;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.soonzlab.englishlearning.client.GreetingService;
import com.soonzlab.englishlearning.client.obj.ArticleObj;
import com.soonzlab.server.AuthDataCenter;
import com.google.api.translate.Language;
import com.google.api.translate.Translate;
import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthUtil;
import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.Entry;
import com.google.gdata.data.Feed;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.data.calendar.ColorProperty;
import com.google.gdata.data.calendar.HiddenProperty;
import com.google.gdata.data.calendar.TimeZoneProperty;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Where;
import com.google.gdata.util.ServiceException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
		GreetingService {

	private static final Logger log = Logger.getLogger(GreetingServiceImpl.class.getName());
	public String greetServer(String input) throws IllegalArgumentException {
		// Verify that the input is valid. 
		

		String serverInfo = getServletContext().getServerInfo();
		String userAgent = getThreadLocalRequest().getHeader("User-Agent");

		// Escape data from the client to avoid cross-site script vulnerabilities.
		input = escapeHtml(input);
		userAgent = escapeHtml(userAgent);

		return "Hello, " + input + "!<br><br>I am running " + serverInfo
				+ ".<br><br>It looks like you are using:<br>" + userAgent;
	}

	@Override
	public ArrayList<ArticleObj> getNewArticle() {

		URL url;
		ArrayList<ArticleObj> array = new ArrayList<ArticleObj>();
		try {
			url = new URL("http://www.voanews.com/templates/Articles.rss?sectionPath=/learningenglish/home");
			SAXReader saxReader = new SAXReader();
		    Document document = saxReader.read(url);

		    Element channel = (Element) document.getRootElement().element("channel");
		    
		    
			    for (Iterator i = channel.elementIterator("item"); i.hasNext();)
	            {
	               Element element = (Element) i.next();
	               String guid = element.elementText("guid");
	               String title = element.elementText("title");
	               String link = element.elementText("link");
	               String description = element.elementText("description");
	               String category = element.elementText("category");
	               String content = element.elementText("encoded");
	               
	               
	               
	               Element source = element.element("enclosure");
	               String picUrl = "";
	               if(source != null){
	            	   Attribute attribute = source.attribute("url");
	            	   picUrl = attribute.getValue();
	               }
	               String audioUrl = "";
	               Date createDate = null; 
	               
	               Element group = element.element("group");
	               
	               ArrayList<String> imageList = new ArrayList<String>();
	               
	               int imageCount = 0;
	               if(group != null){
		               for (Iterator j = group.elementIterator("content"); 
		               j.hasNext();){
		               	Element media = (Element)j.next();
		               	if("image".equals(media.attributeValue("medium"))){
		               		if(imageCount == 0){
		               			imageCount++;
		               		}else{
		               			imageList.add(media.attributeValue("url"));
		               		}
		               	}
		               	
		               	if("audio/mpeg".equals(media.attributeValue("type"))){
		               		audioUrl = media.attributeValue("url");
		               	}
		               }
	               }
	               
	               String dateString = element.elementText("date");
	               dateString = dateString.substring(0, 10);
	               SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	               
	               
	               createDate = dateFormat.parse(dateString);
	               
	               content = dividePhraph(content, imageList);
	               
	               ArticleObj articleObj = new ArticleObj();
	               articleObj.setGuid(guid);
	               articleObj.setTitle(title);
	               articleObj.setOriginUrl(link);
	               articleObj.setDescription(description);
	               articleObj.setCategory(category);
	               articleObj.setAudioUrl(audioUrl);
	               articleObj.setContent(content);
	               articleObj.setPicUrl(picUrl);
	               //articleObj.setCreateDate(createDate);
	               
	               array.add(articleObj);
	            }
		    
		    log.warning("===="+array.size()+"====");
		    return array;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}
	private String articleClean(String origin){
		String expressObj = "</?object(.*?)?>";
		String expressParam = "</?param(.*?)?>";
		//String expressObjEnd = "<//?object(.*?)?>";
		
		origin = origin.replaceAll(expressObj, "");
		origin = origin.replaceAll(expressParam, "");
		
		return origin;
	}
	
	private String dividePhraph(String content, ArrayList<String> imageList){
		
		ArrayList bufArray = new ArrayList();
		
		log.warning("====dividePhraph====");
        String regularxpression = "</?p>(.*?)</?p>";
		
		 	Pattern pattern = Pattern.compile(regularxpression);
		    Matcher matcher = pattern.matcher(content);

		    //StringBuffer sb = new StringBuffer();
		    int phraphCount = 0;
		    StringBuffer tempBuff = new StringBuffer();
		    
		    int imageCount = 0;
		    while(matcher.find()) {

		    	//log.warning("==== match yes====");
		    	
		    		phraphCount++;
		    		String temp = matcher.group();
		    		
		    		if(temp.indexOf("&lt;!--IMAGE--&gt;") != -1){
		    			log.warning("====image phraph====" +  temp);
		    			try{
		    				temp = "<p><img src='"+imageList.get(imageCount)+"'></img></p>";
		    				//temp.replaceAll("&lt;!--IMAGE--&gt;", "<img src='"+imageList.get(imageCount)+"'></img>");
		    			}catch(Exception e){
		    				log.warning("====imageList get error====" +  e.getMessage());
		    			}
		    			imageCount++;
		    		}
		    		
		    		temp = temp.replaceAll("</p>", " <span style='color:#1989FF'>("+phraphCount+")</span> </p>");
		    		tempBuff.append(temp + "\n");

		    	}
				    

		    
		return tempBuff.toString();
	}
	
	
	@Override
	public String getTranslate(String content, String language) {
		
		ArrayList bufArray = new ArrayList();
		
		//StringBuffer contentTrim = new StringBuffer();
        
		//bufArray.add(contentTrim);
		log.warning("====getTranslate====");
        String regularxpression = "</?p>(.*?)</?p>";
		
		 	Pattern pattern = Pattern.compile(regularxpression);
		    Matcher matcher = pattern.matcher(content);

		    StringBuffer sb = new StringBuffer();
		    int bufferUseCount = 0;
		    boolean changeBuffer = false;
		    StringBuffer tempBuff = null;
		    
		    while(matcher.find()) {

		    	//log.warning("==== match yes====");
		    	
		    	//if buffer change , new a buffer
		    	if(changeBuffer){
		    		//log.warning("==== change buffer====");
		    		bufArray.add(tempBuff);
		    		bufferUseCount++;
		    		tempBuff = new StringBuffer();
		    		changeBuffer = false;
		    		tempBuff.append(matcher.group()+"\n");
		    	}else{
		    		
		    		//The First Time
			    	if(bufferUseCount == 0){
			    		//log.warning("==== bufferUseCount == 0====");
			    		tempBuff = new StringBuffer();
			    		bufferUseCount++;
			    	}
		    		
		    		tempBuff.append(matcher.group()+"\n");
		    		
		    		if(tempBuff.length()>3000){
		    			//log.warning("==== tempBuff.length()>3000====");
		    			changeBuffer = true;
			    	}
		    	}
				      }
		    bufArray.add(tempBuff);
		    
		 //System.out.println("==bufArray.size()==" + bufArray.size());
		    Language lan = Language.CHINESE_TRADITIONAL;

		    if(language.equals("CHINESE_SIMPLIFIED")){
		    	lan = Language.CHINESE_SIMPLIFIED;
		    }else if(language.equals("GERMAN")){
		    	lan = Language.GERMAN;
		    }else if(language.equals("FRENCH")){
		    	lan = Language.FRENCH;
		    }else if(language.equals("JAPANESE")){
		    	lan = Language.JAPANESE;
		    }else if(language.equals("KOREAN")){
		    	lan = Language.KOREAN;
		    }else if(language.equals("SPANISH")){
		    	lan = Language.SPANISH;
		    }else if(language.equals("THAI")){
		    	lan = Language.THAI;
		    }else if(language.equals("VIETNAMESE")){
		    	lan = Language.VIETNAMESE;
		    }
		    
		    log.warning("===="+lan+"====");
		    
        StringBuffer translatedText = new StringBuffer();
           try {
        	   for(int i=0; i<bufArray.size(); i++){
        		   
        		   StringBuffer blockBuffer = (StringBuffer)bufArray.get(i);
        		   
        		   Translate.setHttpReferrer("http://soonzsoonz.appspot.com"); 
        		   //log.warning("==temp before =="+blockBuffer.toString()+"====");
        		   
        		   String temp = Translate.execute(blockBuffer.toString(), Language.ENGLISH, lan);
        		   //log.warning("==temp after =="+temp+"====");
        		   
        		   translatedText.append(temp);
        		   
        	   }
        	} catch (Exception ex) {
        	    ex.printStackTrace();
        	    log.warning("===="+ex.getMessage()+"====");
        	    System.out.println(ex.getMessage());
        	}
        //System.out.println(translatedText);
		
		return translatedText.toString();
	}
	
	/**
	 * Escape an html string. Escaping data received from the client helps to
	 * prevent cross-site script vulnerabilities.
	 * 
	 * @param html the html string to escape
	 * @return the escaped string
	 */
	private String escapeHtml(String html) {
		if (html == null) {
			return null;
		}
		return html.replaceAll("&", "&amp;").replaceAll("<", "&lt;")
				.replaceAll(">", "&gt;");
	}
	
	public void logout(){
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession();
		session.removeAttribute("accessToken");
		session.removeAttribute("aSecretToken");
	}
	
	public String saveToCalendar(String word, String vocabulary){
		
		log.warning("==saveToCalendar()=="+word+","+vocabulary+"====");
		String result = "";
		boolean hasError = false;
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession();
		String CONSUMER_KEY = AuthDataCenter.CONSUMER_KEY;
		String CONSUMER_SECRET = AuthDataCenter.CONSUMER_SECRET;
		String accessToken = null; 
		
		log.warning("==saveToCalendar session id=="+session.getId()+"====");

		if(session.getAttribute("accessToken") != null){
			
			accessToken = (String)session.getAttribute("accessToken");
			log.warning("==saveToCalendar()==accessToken:"+accessToken+"====");
			GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
			oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
			oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
			//oauthParameters.setOAuthTokenSecret((String)session.getAttribute("aSecretToken"));
			//log.warning("==saveToCalendar()==aSecretToken:"+(String)session.getAttribute("aSecretToken")+"====");
			oauthParameters.setOAuthToken(accessToken);
			oauthParameters.setOAuthTokenSecret((String)session.getAttribute("aSecretToken"));
			//log.warning("==saveToCalendar()==aSecretToken:"+(String)session.getAttribute("aSecretToken")+"====");


			CalendarService myService = new CalendarService("godshunfenger-exampleApp-2");
			
			URL feedUrl = null;
			CalendarFeed resultFeed = null;
			
			try{
				feedUrl = new URL("https://www.google.com/calendar/feeds/default/owncalendars/full");
				myService.setOAuthCredentials(oauthParameters,new OAuthHmacSha1Signer());
				myService.getFeed(feedUrl, CalendarFeed.class);
				resultFeed = myService.getFeed(feedUrl, CalendarFeed.class);
				boolean hasVocabulary = false;
				CalendarEntry choosedEntry = null;
				for (int i = 0; i < resultFeed.getEntries().size(); i++) {
					CalendarEntry entry = resultFeed.getEntries().get(i);
				  if(entry.getTitle().getPlainText().equals("VOA English Vocabulary")){

					  hasVocabulary = true;
					  choosedEntry = entry;
				  }
				}
				
				if(hasVocabulary){
				  }else{
					  log.warning("==saveToCalendar()==create calendar====");
					CalendarEntry calendar = new CalendarEntry();
					calendar.setTitle(new PlainTextConstruct("VOA English Vocabulary"));
					calendar.setSummary(new PlainTextConstruct("This calendar was created by godshunfenger.appspot.com."));
					calendar.setTimeZone(new TimeZoneProperty("America/Los_Angeles"));
					calendar.setHidden(HiddenProperty.FALSE);
					//calendar.setColor(new ColorProperty("#2952A3"));
					calendar.addLocation(new Where("","","Oakland"));
	
					// Insert the calendar
					URL postUrl = new URL("https://www.google.com/calendar/feeds/default/owncalendars/full");
					CalendarEntry returnedCalendar = myService.insert(postUrl, calendar);
					choosedEntry = returnedCalendar;
				  }
				log.warning("==saveToCalendar()==do search all event====");
				  if(choosedEntry != null){
			    	  
			    	String id = choosedEntry.getId();
			    	id = id.replaceAll("http://www.google.com/calendar/feeds/default/calendars/", "");
					feedUrl = new URL("https://www.google.com/calendar/feeds/" + id + "/private/full");
					CalendarQuery myQuery = new CalendarQuery(feedUrl);
					Calendar calendar = Calendar.getInstance();
					Date now = calendar.getTime();
					DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
					String todayString = dateFormat.format(now);
					myQuery.setMinimumStartTime(DateTime.parseDateTime(todayString + "T00:00:00"));
					myQuery.setMaximumStartTime(DateTime.parseDateTime(todayString + "T23:59:59"));
					// Send the request and receive the response:
					Feed resultFeed2 = myService.query(myQuery, Feed.class);
					boolean hasAdd = false;
			        for (int j = 0; j < resultFeed2.getEntries().size(); j++) {
			          Entry eventEntry = resultFeed2.getEntries().get(j);
			          if(eventEntry.getTitle().getPlainText().toString().equals(word)){
			        	  hasAdd = true;
			          }
			        }
			        
			        if(!hasAdd){
			        	log.warning("==saveToCalendar()==add event====");
			    		URL postUrl = new URL("https://www.google.com/calendar/feeds/" + id + "/private/full");
		        		CalendarEventEntry myEntry = new CalendarEventEntry();
		        		myEntry.setTitle(new PlainTextConstruct(word));
		        		myEntry.setContent(new PlainTextConstruct(vocabulary));
		        		DateTime startTime = DateTime.parseDate(todayString);
		        		DateTime endTime = DateTime.parseDate(todayString);
		        		When eventTimes = new When();
		        		eventTimes.setStartTime(startTime);
		        		eventTimes.setEndTime(endTime);
		        		myEntry.addTime(eventTimes);
	
		        		// Send the request and receive the response:
		        		CalendarEventEntry insertedEntry = myService.insert(postUrl, myEntry);
		        		
		        		//choosedEntry.getService().insert(postUrl, myEntry);
			        		
			        }
				  }
				  result = "Publish the word ," + word + " , to your Google Calendar Successfully.";
			}catch(IOException e){
				log.warning("===="+e.getMessage()+"====");
				hasError = true;
				result = e.getMessage();
			}catch(ServiceException e){
				log.warning("===="+e.getMessage()+"====");
				hasError = true;
				result = e.getMessage();
			
			
			}catch(Exception e){
				log.warning("===="+e.getMessage()+"====");
				hasError = true;
				result = e.getMessage();
			}
		
		}
		
		return result;
	}

	public String getLoginUser() {
		HttpServletRequest request = this.getThreadLocalRequest();
		HttpSession session = request.getSession();
		
		String result = "";
		
		if(session != null && session.getAttribute("accessToken") != null){
			
			log.warning("==session id=="+session.getId()+"====");
			String CONSUMER_KEY = AuthDataCenter.CONSUMER_KEY;
			String CONSUMER_SECRET = AuthDataCenter.CONSUMER_SECRET;
			
			GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
			oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
			oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET);
			oauthParameters.setOAuthTokenSecret((String)session.getAttribute("aSecretToken"));
			log.warning("==getLoginUser()==aSecretToken:"+(String)session.getAttribute("aSecretToken")+"====");
			
			
			String oauth_timestamp = OAuthUtil.getTimestamp();   //oauth要送出的參數資訊，可用google提供的OAuthUtil元件產生
			String oauth_nonce = OAuthUtil.getNonce();   //oauth要送出的參數資訊，可用google提供的OAuthUtil元件產生
			String oauth_token = (String)session.getAttribute("accessToken");   //剛剛取得的access token
			String oauth_signature_method = "HMAC-SHA1";   //編碼方式
			String signature = null;   //準備用來存放簽名的字串
			String oauth_consumer_key = CONSUMER_KEY;
			Map<String, String> params = new HashMap();   //用來產生signature base string的參數
			params.put("oauth_consumer_key", oauth_consumer_key); 
			params.put("oauth_nonce", oauth_nonce); 
			params.put("oauth_signature_method", oauth_signature_method); 
			params.put("oauth_timestamp", oauth_timestamp); 
			params.put("oauth_token", oauth_token); 
			params.put("oauth_version", "1.0"); 
			String signatureBase = null;
			try {
				signatureBase = OAuthUtil.getSignatureBaseString("https://www.googleapis.com/userinfo/email", "GET", params);
				OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();   //編碼方法
				signature = signer.getSignature(signatureBase, oauthParameters);
				//產生signature

				URL url;
				url = new URL("https://www.googleapis.com/userinfo/email");

				HttpURLConnection conn = (HttpURLConnection)url.openConnection();   //建立java HttpURLConnection物件...用來發送request
				conn.setRequestMethod("GET");
				conn.setRequestProperty("HOST","www.googleapis.com");
				
				conn.setRequestProperty("Accept","*/*");
				//送出的參數要經過url encode....可用OAuthUtil.encode完成
				
			conn.setRequestProperty("Authorization","OAuth oauth_version=\"1.0\", oauth_nonce=\""+OAuthUtil.encode(oauth_nonce)+"\", oauth_timestamp=\""+oauth_timestamp+"\", oauth_consumer_key=\""+OAuthUtil.encode(CONSUMER_KEY)+"\", oauth_token=\""+OAuthUtil.encode(oauth_token)+"\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\""+OAuthUtil.encode(signature)+"\"");
				conn.addRequestProperty("Content-Type","application/atom+xml");
				conn.connect();   //連接google送出request
				//接取google傳回的使用者資訊
				BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
				String tmp = "";
				while((tmp=reader.readLine())!=null){
					result += tmp;
				}	
				reader.close();
				
			} catch (Exception e) {
				log.warning("===="+e.getMessage()+"====");
			}   //產生signature base string

			log.warning("===result="+result+"====");
			if(result != null && result.length() != 0){
				log.warning("===result="+result+"====");
				StringTokenizer st = new StringTokenizer(result, "&");
				String temp = st.nextToken();
				result = temp.substring(6, temp.length());
			}
			
			return result;
			
		}
		
		return result;
	}
	
}
